#ifndef Z_ADAPTOR_DEF_H_
#define Z_ADAPTOR_DEF_H_


#include "zfield.h"

typedef ZCharField<1>   ZAdaptorTypeField;
typedef ZDblField<10>   ZAdaptorPriceField;
typedef ZIntField<10>   ZAdaptorSizeField;
typedef ZStrField<9>    ZAdaptorTimestampField;
typedef ZStrField<16>   ZAdaptorNameField;
typedef ZStrField<16>   ZSymbolField;
typedef ZIntField<8>	ZAdaptorOrderIDField;
typedef ZStrField<64>	ZAdaptorTextField;
typedef ZLongField<10>	ZAdaptorSeqNumField;
typedef ZIntField<5>	ZAdaptorInstrumentIndexField;


struct ZAdaptorFlagField : ZIntField<1> {
	enum {Off = 0, On = 1};
};

struct ZAdaptorSideField : ZIntField<3> {
    enum {Buy = 0, Sell = 1};
};

struct ZAdaptorOrderTypeField : ZIntField<1> {
	enum {Ioc = 0, Lmt = 1, Fok = 2, Mkt = 3};
};

struct ZAdaptorOrderActionField : ZIntField<1> {
	enum {Insert = 0, Update = 1, Cancel = 2};
};

struct ZAdaptorOrderStatusField : ZIntField<2> {
	enum Status {
		PendingInsert	= 0,
		PendingFill		= 1,
		PendingUpdate	= 2,
		PendingCancel	= 3,
		PartialFill		= 4,
		Filled			= 5,
		Canceled		= 6,
		RejectInsert	= 7,
		RejectUpdate	= 8,
		RejectCancel	= 9
	};
};

struct ZAdaptorErrorCodeField : ZIntField<3> {
	enum ErrorCode {
		AllOk				= 0,
		OrderLinkNotReady,
		MarketNotOpen,
		DuplicateOrderID,
		WaitForUpdateAck,
		WaitForCancelAck,
		WaitForInsertAck,
		OrderCanceledOrFilled,
		OriginalOrderNotFound,
		LateCancel,
		InstrumentNotFound,
		UnknownError,
	};

	static const char* ErrorMessage(ErrorCode code) {
		switch(code) {
		case AllOk:					return "No error";
		case OrderLinkNotReady:		return "Order link not connected";
		case MarketNotOpen:			return "Market not open";
		case DuplicateOrderID:		return "Duplicated order id";
		case WaitForUpdateAck:		return "Wait for update ack";
		case WaitForCancelAck:		return "Wait for cancel ack";
		case WaitForInsertAck:		return "Wait for insert ack";
		case LateCancel:			return "Late cancel";
		case InstrumentNotFound:	return "Instrument not found";
		case OriginalOrderNotFound:	return "Original order not found";
		case OrderCanceledOrFilled:	return "Order has already been canceled or filled";
		default:					return "Unknown error";
		}
	}
};

typedef ZFixedLengthField<ZAdaptorTypeField>			ZMessageType;
typedef ZFixedLengthField<ZSymbolField>					ZSymbol;
typedef ZFixedLengthField<ZAdaptorPriceField>			ZOrderPrice;
typedef ZFixedLengthField<ZAdaptorSizeField>			ZOrderSize;
typedef ZFixedLengthField<ZAdaptorSideField>			ZOrderSide;
typedef ZFixedLengthField<ZAdaptorTimestampField>		ZTimestamp;
typedef ZFixedLengthField<ZAdaptorOrderTypeField>		ZOrderType;
typedef ZFixedLengthField<ZAdaptorOrderActionField>		ZOrderAction;
typedef ZFixedLengthField<ZAdaptorOrderIDField>			ZOrderID;
typedef ZFixedLengthField<ZAdaptorNameField>			ZName;
typedef ZFixedLengthField<ZAdaptorOrderStatusField>		ZOrderStatus;
typedef ZFixedLengthField<ZAdaptorTextField>			ZOrderText;
typedef ZFixedLengthField<ZAdaptorErrorCodeField>		ZErrorCode;
typedef ZFixedLengthField<ZAdaptorFlagField>			ZFlag;
typedef ZFixedLengthField<ZAdaptorSeqNumField>			ZSeqNum;
typedef ZFixedLengthField<ZAdaptorInstrumentIndexField>	ZInstrumentIndex;

typedef ZOrderSize	ZOrderTotalFilledSize;
typedef ZOrderSize	ZOrderCurrentFilledSize;
typedef ZOrderPrice	ZOrderFilledPrice;
typedef ZOrderSize	ZOrderRemainSize;
typedef ZOrderPrice ZLastPx;
typedef ZOrderSize	ZLastSz;
typedef ZOrderSize	ZVolume;
typedef ZOrderPrice ZMktBidPx1;
typedef ZOrderPrice ZMktAskPx1;
typedef ZOrderSize	ZMktBidSz1;
typedef ZOrderSize	ZMktAskSz1;

#define OrderMessageType				'0'
#define OrderStatusMessageType			'1'
#define LoginMessageType				'2'
#define LoginStatusMessageType			'3'
#define MarketDataSubMessageType		'4'
#define MarketDataSubStatusMessageType	'5'
#define MarketDataBestLevelMessageType	'6'
#define MarketDataTradeMessageType		'7'

struct ZAdaptorOrderMessage {
    enum {
		Type = OrderMessageType,
		Length = ZMessageType::Length + ZSymbol::Length + ZOrderPrice::Length +
		ZOrderSize::Length + ZOrderSide::Length + ZTimestamp::Length + ZOrderType::Length +
		ZOrderAction::Length + ZOrderID::Length
	};
	ZAdaptorOrderMessage() {
		zTypeField.zVal = Type;
	}
	ZMessageType	zTypeField;
    ZSymbol         zSymbolField;
    ZOrderPrice     zPriceField;
    ZOrderSize      zSizeField;
    ZOrderSide      zSideField;
	ZTimestamp		zTimestampField;
	ZOrderType		zOrderTypeField;
	ZOrderAction	zOrderActionField;
	ZOrderID		zOrderIDField;
    static bool get(const char* data, int len, ZAdaptorOrderMessage *msg) {
		return  msg->zTypeField.get(&data, &len) &&
                msg->zSymbolField.get(&data, &len) &&
                msg->zPriceField.get(&data, &len) &&
                msg->zSizeField.get(&data, &len) &&
                msg->zSideField.get(&data, &len) &&
                msg->zTimestampField.get(&data, &len) &&
				msg->zOrderTypeField.get(&data, &len) &&
				msg->zOrderActionField.get(&data, &len) &&
				msg->zOrderIDField.get(&data, &len);
    }
    static int set(char *data, ZAdaptorOrderMessage *msg) {
        int len = 0;
        msg->zTypeField.set(&data, &len);
        msg->zSymbolField.set(&data, &len);
        msg->zPriceField.set(&data, &len);
        msg->zSizeField.set(&data, &len);
        msg->zSideField.set(&data, &len);
        msg->zTimestampField.set(&data, &len);
		msg->zOrderTypeField.set(&data, &len);
		msg->zOrderActionField.set(&data, &len);
		msg->zOrderIDField.set(&data, &len);
        return len;
    }
};

struct ZAdaptorOrderStatusMessage {
	enum {
		Type = OrderStatusMessageType,
		Length = ZMessageType::Length + ZSymbol::Length + ZOrderID::Length + ZOrderStatus::Length + ZOrderTotalFilledSize::Length + 
		ZOrderCurrentFilledSize::Length + ZOrderFilledPrice::Length + ZOrderText::Length + ZOrderRemainSize::Length + ZErrorCode::Length
	};
	ZAdaptorOrderStatusMessage() {
		zTypeField.zVal = Type;
	}
	ZMessageType			zTypeField;
	ZSymbol					zSymbolField;
	ZOrderID				zOrderIDField;
	ZOrderStatus			zOrderStatusField;
	ZOrderTotalFilledSize	zTotalFilledSizeField;
	ZOrderCurrentFilledSize	zCurrentFilledSizeFiled;
	ZOrderFilledPrice		zFilledPriceField;
	ZOrderRemainSize		zRemainSizeField;
	ZErrorCode				zErrorCodeField;
	ZOrderText				zOrderTextField;
	static bool get(const char *data, int len, ZAdaptorOrderStatusMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zOrderIDField.get(&data, &len) &&
				msg->zSymbolField.get(&data, &len) &&
				msg->zOrderStatusField.get(&data, &len) &&
				msg->zTotalFilledSizeField.get(&data, &len) &&
				msg->zFilledPriceField.get(&data, &len) &&
				msg->zCurrentFilledSizeFiled.get(&data, &len) &&
				msg->zRemainSizeField.get(&data, &len) &&
				msg->zErrorCodeField.get(&data, &len) &&
				msg->zOrderTextField.get(&data, &len);
	}
	static int set(char *data, ZAdaptorOrderStatusMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zOrderIDField.set(&data, &len);
		msg->zSymbolField.set(&data, &len);
		msg->zOrderStatusField.set(&data, &len);
		msg->zTotalFilledSizeField.set(&data, &len);
		msg->zFilledPriceField.set(&data, &len);
		msg->zCurrentFilledSizeFiled.set(&data, &len);
		msg->zRemainSizeField.set(&data, &len);
		msg->zErrorCodeField.set(&data, &len);
		msg->zOrderTextField.set(&data, &len);
		return len;
	}
};

struct ZAdaptorLoginMessage {
    enum {
		Type = LoginMessageType,
		Length = ZMessageType::Length + ZName::Length
	};
	ZAdaptorLoginMessage() {
		zTypeField.zVal = Type;
	}
	ZMessageType	zTypeField;
	ZName			zNameField;
    static bool get(const char* data, int len, ZAdaptorLoginMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zNameField.get(&data, &len);
    }
    static int set(char *data, ZAdaptorLoginMessage *msg) {
        int len = 0;
        msg->zTypeField.set(&data, &len);
        msg->zNameField.set(&data, &len);
        return len;
    }
};


struct ZAdaptorLoginStatusMessage {
	enum {
		Type = LoginStatusMessageType,
		Length = ZMessageType::Length + ZErrorCode::Length
	};
	ZAdaptorLoginStatusMessage() {
		zTypeField.zVal = Type;
	}

	ZMessageType			zTypeField;
	ZErrorCode				zErrorCodeField;

	static bool get(const char* data, int len, ZAdaptorLoginStatusMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zErrorCodeField.get(&data, &len);
	}
	static int set(char *data, ZAdaptorLoginStatusMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zErrorCodeField.set(&data, &len);
		return len;
	}
};

struct ZAdaptorMarketDataSubMessage {
    enum {
		Type = MarketDataSubMessageType,
		Length = ZMessageType::Length + ZFlag::Length + ZSymbol::Length
	};
	ZAdaptorMarketDataSubMessage() {
		zTypeField.zVal = Type;
	}
	ZMessageType        zTypeField;
	ZFlag				zFlagField;
	ZSymbol				zSymbolField;
	static bool get(const char* data, int len, ZAdaptorMarketDataSubMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zFlagField.get(&data, &len) &&
				msg->zSymbolField.get(&data, &len);
	}
	static int set(char *data, ZAdaptorMarketDataSubMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zFlagField.set(&data, &len);
		msg->zSymbolField.set(&data, &len);
		return len;
	}
};


struct ZAdaptorMarketDataSubStatusMessage {
	enum {
		Type = MarketDataSubStatusMessageType,
		Length = ZMessageType::Length + ZSymbol::Length + ZInstrumentIndex::Length + ZFlag::Length + ZErrorCode::Length
	};

	ZAdaptorMarketDataSubStatusMessage() {
		zTypeField.zVal = Type;
	}

	static bool get(const char *data, int len, ZAdaptorMarketDataSubStatusMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zInstrumentIndexField.get(&data, &len) &&
				msg->zSymbolField.get(&data, &len) &&
				msg->zFlagField.get(&data, &len) &&
				msg->zErrorCodeField.get(&data, &len);
	}

	static int set(char *data, ZAdaptorMarketDataSubStatusMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zInstrumentIndexField.set(&data, &len);
		msg->zSymbolField.set(&data, &len);
		msg->zFlagField.set(&data, &len);
		msg->zErrorCodeField.set(&data, &len);
		return len;
	}

	ZMessageType        zTypeField;
	ZSymbol				zSymbolField;
	ZInstrumentIndex	zInstrumentIndexField;
	ZFlag				zFlagField;
	ZErrorCode			zErrorCodeField;
};

struct ZAdaptorMarketDataBestLevelMessage {
	enum {
		Type = MarketDataBestLevelMessageType,
		Length = ZMessageType::Length + ZSymbol::Length + ZMktBidPx1::Length + ZMktBidSz1::Length + 
		ZMktAskPx1::Length + ZMktAskSz1::Length + ZTimestamp::Length
	};
	ZAdaptorMarketDataBestLevelMessage() {
		zTypeField.zVal = Type;
		zBestBidPxField.zVal = 0;
		zBestAskPxField.zVal = 0;
		zBestBidSzField.zVal = 0;
		zBestAskSzField.zVal = 0;
	}
	static bool get(const char *data, int len, ZAdaptorMarketDataBestLevelMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zSymbolField.get(&data, &len) &&
				msg->zBestBidPxField.get(&data, &len) &&
				msg->zBestBidSzField.get(&data, &len) &&
				msg->zBestAskPxField.get(&data, &len) &&
				msg->zBestAskSzField.get(&data, &len) &&
				msg->zTimestampField.get(&data, &len);
	}
	static int set(char *data, ZAdaptorMarketDataBestLevelMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zSymbolField.set(&data, &len);
		msg->zBestBidPxField.set(&data, &len);
		msg->zBestBidSzField.set(&data, &len);
		msg->zBestAskPxField.set(&data, &len);
		msg->zBestAskSzField.set(&data, &len);
		msg->zTimestampField.set(&data, &len);
		return len;
	}
	ZMessageType		zTypeField;
	ZSymbol				zSymbolField;
	ZMktBidPx1			zBestBidPxField;
	ZMktBidSz1			zBestBidSzField;
	ZMktAskPx1			zBestAskPxField;
	ZMktAskSz1			zBestAskSzField;
	ZTimestamp			zTimestampField;
};

struct ZAdaptorMarketDataTradeMessage {
	enum {
		Type = MarketDataTradeMessageType,
		Length = ZMessageType::Length + ZSymbol::Length + ZLastPx::Length + ZLastSz::Length + ZTimestamp::Length + ZVolume::Length
	};
	ZAdaptorMarketDataTradeMessage() {
		zTypeField.zVal = Type;
		zLastPxField.zVal = 0;
		zLastSzField.zVal = 0;
		zVolumeField.zVal = 0;
	}
	static bool get(const char *data, int len, ZAdaptorMarketDataTradeMessage *msg) {
		return	msg->zTypeField.get(&data, &len) &&
				msg->zSymbolField.get(&data, &len) &&
				msg->zLastPxField.get(&data, &len) &&
				msg->zLastSzField.get(&data, &len) &&
				msg->zVolumeField.get(&data, &len) &&
				msg->zTimestampField.get(&data, &len);
	}
	static int set(char *data, ZAdaptorMarketDataTradeMessage *msg) {
		int len = 0;
		msg->zTypeField.set(&data, &len);
		msg->zSymbolField.set(&data, &len);
		msg->zLastPxField.set(&data, &len);
		msg->zLastSzField.set(&data, &len);
		msg->zVolumeField.set(&data, &len);
		msg->zTimestampField.set(&data, &len);
		return len;
	}
	ZMessageType		zTypeField;
	ZSymbol				zSymbolField;
	ZLastPx				zLastPxField;
	ZLastSz				zLastSzField;
	ZVolume				zVolumeField;
	ZTimestamp			zTimestampField;
};

#endif // Z_ADAPTOR_DEF_H_
